//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#include "sdram_bsp.h"
#include <stdio.h>

/*延迟一段时间*/
static inline void SDRAM_delay(volatile unsigned int nCount)
{
    for (volatile unsigned int index = (100000 * nCount); index != 0; index--)
    {
    }
}
/*初始化控制SDRAM的IO*/
static void SDRAM_BSP_GPIO_Init(void)
{
    /*地址信号线*/
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A0_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A1_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A2_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A3_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A4_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A5_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A6_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A7_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A8_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A9_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A10_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A11_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_BA0_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_BA1_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A0_GPIO_PORT, FMC_A0_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A1_GPIO_PORT, FMC_A1_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A2_GPIO_PORT, FMC_A2_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A3_GPIO_PORT, FMC_A3_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A4_GPIO_PORT, FMC_A4_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A5_GPIO_PORT, FMC_A5_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A6_GPIO_PORT, FMC_A6_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A7_GPIO_PORT, FMC_A7_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A8_GPIO_PORT, FMC_A8_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A9_GPIO_PORT, FMC_A9_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A10_GPIO_PORT, FMC_A10_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A11_GPIO_PORT, FMC_A11_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_BA0_GPIO_PORT, FMC_BA0_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_BA1_GPIO_PORT, FMC_BA1_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A0_GPIO_PORT, FMC_A0_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A1_GPIO_PORT, FMC_A1_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A2_GPIO_PORT, FMC_A2_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A3_GPIO_PORT, FMC_A3_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A4_GPIO_PORT, FMC_A4_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A5_GPIO_PORT, FMC_A5_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A6_GPIO_PORT, FMC_A6_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A7_GPIO_PORT, FMC_A7_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A8_GPIO_PORT, FMC_A8_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A9_GPIO_PORT, FMC_A9_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A10_GPIO_PORT, FMC_A10_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A11_GPIO_PORT, FMC_A11_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_BA0_GPIO_PORT, FMC_BA0_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_BA1_GPIO_PORT, FMC_BA1_GPIO_PIN, AFIO_EXMC);
    /*数据信号线*/
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D0_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D1_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D2_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D3_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D4_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D5_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D6_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D7_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D8_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D9_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D10_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D11_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D12_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D13_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D14_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D15_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D0_GPIO_PORT, FMC_D0_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D1_GPIO_PORT, FMC_D1_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D2_GPIO_PORT, FMC_D2_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D3_GPIO_PORT, FMC_D3_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D4_GPIO_PORT, FMC_D4_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D5_GPIO_PORT, FMC_D5_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D6_GPIO_PORT, FMC_D6_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D7_GPIO_PORT, FMC_D7_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D8_GPIO_PORT, FMC_D8_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D9_GPIO_PORT, FMC_D9_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D10_GPIO_PORT, FMC_D10_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D11_GPIO_PORT, FMC_D11_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D12_GPIO_PORT, FMC_D12_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D13_GPIO_PORT, FMC_D13_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D14_GPIO_PORT, FMC_D14_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D15_GPIO_PORT, FMC_D15_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D0_GPIO_PORT, FMC_D0_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D1_GPIO_PORT, FMC_D1_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D2_GPIO_PORT, FMC_D2_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D3_GPIO_PORT, FMC_D3_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D4_GPIO_PORT, FMC_D4_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D5_GPIO_PORT, FMC_D5_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D6_GPIO_PORT, FMC_D6_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D7_GPIO_PORT, FMC_D7_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D8_GPIO_PORT, FMC_D8_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D9_GPIO_PORT, FMC_D9_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D10_GPIO_PORT, FMC_D10_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D11_GPIO_PORT, FMC_D11_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D12_GPIO_PORT, FMC_D12_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D13_GPIO_PORT, FMC_D13_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D14_GPIO_PORT, FMC_D14_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D15_GPIO_PORT, FMC_D15_GPIO_PIN, AFIO_EXMC);
    /*控制信号线*/
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_CS_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_WE_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_RAS_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_CAS_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_CLK_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_CKE_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_UDQM_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_LDQM_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_CS_GPIO_PORT, FMC_CS_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_WE_GPIO_PORT, FMC_WE_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_RAS_GPIO_PORT, FMC_RAS_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_CAS_GPIO_PORT, FMC_CAS_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_CLK_GPIO_PORT, FMC_CLK_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_CKE_GPIO_PORT, FMC_CKE_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_UDQM_GPIO_PORT, FMC_UDQM_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_LDQM_GPIO_PORT, FMC_LDQM_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_CS_GPIO_PORT, FMC_CS_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_WE_GPIO_PORT, FMC_WE_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_RAS_GPIO_PORT, FMC_RAS_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_CAS_GPIO_PORT, FMC_CAS_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_CLK_GPIO_PORT, FMC_CLK_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_CKE_GPIO_PORT, FMC_CKE_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_UDQM_GPIO_PORT, FMC_UDQM_GPIO_PIN, AFIO_EXMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_LDQM_GPIO_PORT, FMC_LDQM_GPIO_PIN, AFIO_EXMC);		
}
/*对SDRAM芯片进行初始化配置*/
static void SDRAM_BSP_Config_Init(void)
{
    exmc_sdram_command_parameter_struct     FMC_SDRAMCommandStruct;
    unsigned int tmpr = 0;
    
    /* Step 3:配置命令：开启提供给SDRAM的时钟 */
    FMC_SDRAMCommandStruct.command = EXMC_SDRAM_CLOCK_ENABLE;
    FMC_SDRAMCommandStruct.bank_select = FMC_COMMAND_TARGET_BANK;
    FMC_SDRAMCommandStruct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_2_SDCLK;
    FMC_SDRAMCommandStruct.mode_register_content = 0;
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(exmc_flag_get(FMC_BANK_SDRAM, EXMC_SDRAM_FLAG_NREADY) != RESET)
    {
    }
    /* 发送上述命令*/
    exmc_sdram_command_config(&FMC_SDRAMCommandStruct);
  
    /* Step 4:延时 */
    SDRAM_delay(10);
    
    /* Step 5：配置命令：对所有的bank预充电 */
    FMC_SDRAMCommandStruct.command = EXMC_SDRAM_PRECHARGE_ALL;
    FMC_SDRAMCommandStruct.bank_select = FMC_COMMAND_TARGET_BANK;
    FMC_SDRAMCommandStruct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_2_SDCLK;
    FMC_SDRAMCommandStruct.mode_register_content = 0;
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(exmc_flag_get(FMC_BANK_SDRAM, EXMC_SDRAM_FLAG_NREADY) != RESET)
    {
    }
    /* 发送上述命令*/
    exmc_sdram_command_config(&FMC_SDRAMCommandStruct);
  
    /* Step 6：配置命令：自动刷新 */   
    FMC_SDRAMCommandStruct.command = EXMC_SDRAM_AUTO_REFRESH;
    FMC_SDRAMCommandStruct.bank_select = FMC_COMMAND_TARGET_BANK;
    FMC_SDRAMCommandStruct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_9_SDCLK; //9个自动刷新命令
    FMC_SDRAMCommandStruct.mode_register_content = 0;
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(exmc_flag_get(FMC_BANK_SDRAM, EXMC_SDRAM_FLAG_NREADY) != RESET)
    {
    }
    /* 发送自动刷新命令*/
    exmc_sdram_command_config(&FMC_SDRAMCommandStruct);
    
    /* Step 7：设置sdram寄存器配置 */
    tmpr = SDRAM_MODEREG_BURST_LENGTH_1 | SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
            SDRAM_MODEREG_CAS_LATENCY_3 | SDRAM_MODEREG_OPERATING_MODE_STANDARD |
            SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
    
    /* 配置命令：设置SDRAM寄存器 */
    FMC_SDRAMCommandStruct.command = EXMC_SDRAM_LOAD_MODE_REGISTER;
    FMC_SDRAMCommandStruct.bank_select = FMC_COMMAND_TARGET_BANK;
    FMC_SDRAMCommandStruct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_2_SDCLK;
    FMC_SDRAMCommandStruct.mode_register_content = tmpr;
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(exmc_flag_get(FMC_BANK_SDRAM, EXMC_SDRAM_FLAG_NREADY) != RESET)
    {
    }
    /* 发送上述命令*/
    exmc_sdram_command_config(&FMC_SDRAMCommandStruct);
  
    /* Step 8：设置刷新计数器 */
	/*刷新速率 = (COUNT + 1) x SDRAM 频率时钟 COUNT =（ SDRAM 刷新周期/行数) - 20*/
    /* 64ms, 8192-cycle refresh, 64ms/8192=7.81us */
    /* SDCLK_Freq = SYS_Freq/2 */
    /* (7.81 us * SDCLK_Freq) - 20 */
    exmc_sdram_refresh_count_set(761);
    /* 发送上述命令*/
    while(exmc_flag_get(FMC_BANK_SDRAM, EXMC_SDRAM_FLAG_NREADY) != RESET)
    {
    }
}
/*初始化配置使用SDRAM的FMC及GPIO接口，本函数在SDRAM读写操作前需要被调用*/
static ErrStatus SDRAM_BSP_Register(void)
{
    exmc_sdram_parameter_struct        FMC_SDRAMInitStruct;
    exmc_sdram_timing_parameter_struct  FMC_SDRAMTimingStruct;
    
    /* 配置FMC接口相关的 GPIO*/
    SDRAM_BSP_GPIO_Init();
    
    /* 使能 FMC 时钟 */
    rcu_periph_clock_enable(RCU_EXMC);
    
    /* SDRAM时序结构体，根据SDRAM参数表配置----------------*/
    /* LMRD: 2 clock cycles */
    FMC_SDRAMTimingStruct.load_mode_register_delay = 2;
    /* XSRD: min = 67ns */
    FMC_SDRAMTimingStruct.exit_selfrefresh_delay = 7;
    /* RASD: min=42ns , max=120k (ns) */
    FMC_SDRAMTimingStruct.row_address_select_delay = 5;
    /* ARFD: min=60ns */
    FMC_SDRAMTimingStruct.auto_refresh_delay = 6;
    /* WRD:  min=1 Clock cycles +6ns */
    FMC_SDRAMTimingStruct.write_recovery_delay = 2;
    /* RPD:  min=18ns */
    FMC_SDRAMTimingStruct.row_precharge_delay = 2;
    /* RCD:  min=18ns */
    FMC_SDRAMTimingStruct.row_to_column_delay = 2;

    /* FMC SDRAM 控制配置 */
    /*选择存储区域*/
    FMC_SDRAMInitStruct.sdram_device = FMC_BANK_SDRAM;
    /* 行地址线宽度: [7:0] */
    FMC_SDRAMInitStruct.column_address_width = EXMC_SDRAM_COW_ADDRESS_8;
    /* 列地址线宽度: [11:0] */
    FMC_SDRAMInitStruct.row_address_width = EXMC_SDRAM_ROW_ADDRESS_12;
    /* 数据线宽度 */
    FMC_SDRAMInitStruct.data_width = SDRAM_MEMORY_WIDTH; 
    /* SDRAM内部bank数量*/
    FMC_SDRAMInitStruct.internal_bank_number = EXMC_SDRAM_4_INTER_BANK;
    /* CAS潜伏期 */
    FMC_SDRAMInitStruct.cas_latency = SDRAM_CAS_LATENCY; 
    /* 禁止写保护*/
    FMC_SDRAMInitStruct.write_protection = DISABLE;
    /* SDCLK时钟分频因子，SDCLK = HCLK/SDCLOCK_PERIOD*/
    FMC_SDRAMInitStruct.sdclock_config = SDCLOCK_PERIOD; 
    /* 突发读模式设置*/  
    FMC_SDRAMInitStruct.burst_read_switch = SDRAM_READBURST;
    /* 读延迟配置 */
    FMC_SDRAMInitStruct.pipeline_read_delay = EXMC_PIPELINE_DELAY_2_HCLK;
    /* SDRAM时序参数 */
    FMC_SDRAMInitStruct.timing = &FMC_SDRAMTimingStruct;
    
    /* 调用初始化函数，向寄存器写入配置 */
    exmc_sdram_init(&FMC_SDRAMInitStruct); 
    /* 执行FMC SDRAM的初始化流程*/
    SDRAM_BSP_Config_Init();
    return SUCCESS;
}


/*Waiting SDRAM Idle*/
static void SDRAM_BSP_Waiting_Idle(void)
{
    /* 禁止写保护 */
    exmc_sdram_write_protection_config(FMC_BANK_SDRAM, DISABLE);
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(exmc_flag_get(FMC_BANK_SDRAM, EXMC_SDRAM_FLAG_NREADY) != RESET)
    {
    }
}

/*按照1字节写SDRAM*/
static void SDRAM_BSP_Write_1Byte(const unsigned char* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned char* Datax = (unsigned char*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *Datax++ = *buffer++;
    }
}
/*按照1字节读SDRAM*/
static void SDRAM_BSP_Read_1Byte(unsigned char* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned char* Datax = (unsigned char*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *buffer++ = *Datax++;
    }
}

/*按照2字节写SDRAM*/
static void SDRAM_BSP_Write_2Byte(const unsigned short* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned short* Datax = (unsigned short*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *Datax++ = *buffer++;
    }
}
/*按照2字节读SDRAM*/
static void SDRAM_BSP_Read_2Byte(unsigned short* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned short* Datax = (unsigned short*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *buffer++ = *Datax++;
    }
}

/*按照4节写SDRAM*/
static void SDRAM_BSP_Write_4Byte(const unsigned int* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned int* Datax = (unsigned int*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *Datax++ = *buffer++;
    }
}
/*按照4字节读SDRAM*/
static void SDRAM_BSP_Read_4Byte(unsigned int* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned int* Datax = (unsigned int*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *buffer++ = *Datax++;
    }
}

/*使用DMA写SDRAM*/
static void SDRAM_BSP_Write_DMA(const void* buffer, unsigned int address, unsigned int size)
{
    SDRAM_BSP_Waiting_Idle();
    WHT_DMA_BSP_Memcpy((void*)(SDRAM_BANK_ADDR + address), buffer, size);//无法知道传输的状态
}
/*使用DMA读SDRAM*/
static void SDRAM_BSP_Read_DMA(void* buffer, unsigned int address, unsigned int size)
{
    SDRAM_BSP_Waiting_Idle();
    WHT_DMA_BSP_Memcpy(buffer, (void*)(SDRAM_BANK_ADDR + address), size);//无法知道传输的状态
}

const WHT_SDRAM_BSP_t WHT_SDRAM_BSP =
{
    .WHT_Register    = SDRAM_BSP_Register,
    .WHT_Write_1Byte = SDRAM_BSP_Write_1Byte,
    .WHT_Write_2Byte = SDRAM_BSP_Write_2Byte,
    .WHT_Write_4Byte = SDRAM_BSP_Write_4Byte,
    .WHT_Read_1Byte  = SDRAM_BSP_Read_1Byte,
    .WHT_Read_2Byte  = SDRAM_BSP_Read_2Byte,
    .WHT_Read_4Byte  = SDRAM_BSP_Read_4Byte,
    .WHT_Write_DMA   = SDRAM_BSP_Write_DMA,
    .WHT_Read_DMA    = SDRAM_BSP_Read_DMA,
};
